﻿#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"


#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "oled_driver.h"


#define GPIO_OUTPUT_IO_SDA   4
#define GPIO_OUTPUT_IO_SCL  15
#define GPIO_OUTPUT_IO_RST  16
#define GPIO_OUTPUT_PIN_OLED   ((1<<GPIO_OUTPUT_IO_SCL)|(1<<GPIO_OUTPUT_IO_SDA)|(1<<GPIO_OUTPUT_IO_RST))
#define GPIO_Set_SDA    gpio_set_level(GPIO_OUTPUT_IO_SDA, 1)
#define GPIO_Set_SCL    gpio_set_level(GPIO_OUTPUT_IO_SCL, 1)
#define GPIO_Set_RST    gpio_set_level(GPIO_OUTPUT_IO_RST, 1)

#define GPIO_Clean_SDA  gpio_set_level(GPIO_OUTPUT_IO_SDA, 0)
#define GPIO_Clean_SCL  gpio_set_level(GPIO_OUTPUT_IO_SCL, 0)
#define GPIO_Clean_RST  gpio_set_level(GPIO_OUTPUT_IO_RST, 0)


/***************************************/
//函数：   模拟IIC的延时函数
//输入：
//输出：
//作者：
/***************************************/
void delay_IIC(uint32_t time)
{
    //	uint32_t n=time*5;
    //	while(n!=0)
    //		n--;
    vTaskDelay(time / 1000);
}



/***************************************/
//函数：     IIC引脚初始化
//输入：
//输出：
//作者：
/***************************************/
void IIC_init(void )
{
    //初始化GPIO引脚
    gpio_config_t io_conf;
    //disable interrupt
    io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
    //set as output mode
    io_conf.mode = GPIO_MODE_OUTPUT;
    //bit mask of the pins that you want to set,e.g.GPIO35
    io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_OLED;
    //disable pull-down mode
    io_conf.pull_down_en = 0;
    //disable pull-up mode
    io_conf.pull_up_en = 0;
    //configure GPIO with the given settings
    gpio_config(&io_conf);
}

/***************************************/
//函数：     IIC start
//输入：
//输出：
//作者：
/***************************************/
void IIC_start()
{

    GPIO_Set_SDA;
    GPIO_Set_SDA;
    GPIO_Clean_SDA;
    GPIO_Clean_SCL;
}

/***************************************/
//函数：     IIC STOP
//输入：
//输出：
/***************************************/
void IIC_stop()
{
    GPIO_Clean_SCL;
    GPIO_Clean_SDA;
    GPIO_Set_SCL;
    GPIO_Set_SDA;
}

/***************************************/
//函数：     Write_IIC_Byte
//输入：
//输出：
//作者：
/***************************************/
void Write_IIC_Byte(uint8_t IIC_Byte)//I2C_WriteByte(uint8_t addr,uint8_t data)
{
    uint8_t i = 0;
    for( i = 0; i < 8; i++){
        if(IIC_Byte & 0x80){
            GPIO_Set_SDA;
        }else{
            GPIO_Clean_SDA;
        }
        GPIO_Set_SCL;
        GPIO_Clean_SCL;
        IIC_Byte <<= 1;
    }
    GPIO_Set_SDA;
    GPIO_Set_SCL;
    GPIO_Clean_SCL;
}



/***************************************/
//函数：     I2C_WriteByte
//输入：
//输出：
//作者：
/***************************************/
void I2C_WriteByte(uint8_t addr,uint8_t data)
{
    IIC_start();
    Write_IIC_Byte(0x78);
    Write_IIC_Byte(addr);			//write data
    Write_IIC_Byte(data);
    IIC_stop();
}


/***************************************/
//函数：     WriteCmd和WriteDat
//输入：
//输出：
//作者：
/***************************************/
void WriteCmd(unsigned char I2C_Command)//写命令
{
    I2C_WriteByte(0x00, I2C_Command);
}

void WriteDat(unsigned char I2C_Data)//写数据
{
    I2C_WriteByte(0x40, I2C_Data);
}

/***************************************/
//函数：     OLED_Init
//输入：
//输出：
//作者：
/***************************************/
void OLED_Init(void)
{
    IIC_init();
    GPIO_Set_RST;
    delay_IIC(200); //这里的延时很重要
    GPIO_Clean_RST;
    delay_IIC(200); //这里的延时很重要
    GPIO_Set_RST;
    delay_IIC(200); //这里的延时很重要

    WriteCmd(0xAE); //display off
    WriteCmd(0x20);	//Set Memory Addressing Mode
    WriteCmd(0x10);	//00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
    WriteCmd(0xb0);	//Set Page Start Address for Page Addressing Mode,0-7
    WriteCmd(0xc8);	//Set COM Output Scan Direction
    WriteCmd(0x00); //---set low column address
    WriteCmd(0x10); //---set high column address
    WriteCmd(0x40); //--set start line address
    WriteCmd(0x81); //--set contrast control register
    WriteCmd(0xff); //亮度调节 0x00~0xff
    WriteCmd(0xa1); //--set segment re-map 0 to 127
    WriteCmd(0xa6); //--set normal display
    WriteCmd(0xa8); //--set multiplex ratio(1 to 64)
    WriteCmd(0x3F); //
    WriteCmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
    WriteCmd(0xd3); //-set display offset
    WriteCmd(0x00); //-not offset
    WriteCmd(0xd5); //--set display clock divide ratio/oscillator frequency
    WriteCmd(0xf0); //--set divide ratio
    WriteCmd(0xd9); //--set pre-charge period
    WriteCmd(0x22); //
    WriteCmd(0xda); //--set com pins hardware configuration
    WriteCmd(0x12);
    WriteCmd(0xdb); //--set vcomh
    WriteCmd(0x20); //0x20,0.77xVcc
    WriteCmd(0x8d); //--set DC-DC enable
    WriteCmd(0x14); //
    WriteCmd(0xaf); //--turn on oled panel
}

void OLED_SetPos(unsigned char x, unsigned char y) //设置起始点坐标
{
    WriteCmd(0xb0+y);
    WriteCmd(((x&0xf0)>>4)|0x10);
    WriteCmd((x&0x0f)|0x01);
}


/**************************************/
/**************************************/
//画点函数：SetDot():
//							：x,y  坐标
//							：color  :颜色  0：白  1：黑
//
/**************************************/
void SetDot(unsigned char x,unsigned char y,int color)
{
    int a,b;
    unsigned char c;
    a = y / 8;
    b = y % 8;

    if (color==1){
        c = (0x01<<b);
    }else{
        c = (0x01<<b);
        c = ~c;
    }

    OLED_SetPos(x,a);
    WriteDat(c);
}

/***************************************/
//函数：     OLED_Fill
//输入：
//输出：
//作者：
/***************************************/
void OLED_Fill(unsigned char fill_Data)//全屏填充
{
    unsigned char m, n;
    for(m = 0; m < 8; m++){
        WriteCmd(0xb0 + m);	//page0-page1
        WriteCmd(0x00);		//low column start address
        WriteCmd(0x10);		//high column start address
        for(n=0;n<128;n++){
            WriteDat(fill_Data);
        }
    }
}

/***************************************/
//函数：     OLED_CLS
//输入：
//输出：
//作者：
/***************************************/
void OLED_CLS(void)//清屏
{
    OLED_Fill(0x00);
}

/***************************************/
//函数：     OLED_ON
//输入：
//输出：
//作者：
/***************************************/
void OLED_ON(void)
{
    WriteCmd(0X8D);  //设置电荷泵
    WriteCmd(0X14);  //开启电荷泵
    WriteCmd(0XAF);  //OLED唤醒
}


/***************************************/
//函数：     OLED_OFF 让OLED休眠 -- 休眠模式下,OLED功耗不到10uA
//输入：
//输出：
//作者：
/***************************************/
void OLED_OFF(void)
{
    WriteCmd(0X8D);  //设置电荷泵
    WriteCmd(0X10);  //关闭电荷泵
    WriteCmd(0XAE);  //OLED休眠
}









